package com.lancoo.ccas53.arrangecourse.clashesprocess;

import com.lancoo.ccas53.arrangecourse.common.StrUtil;
import com.lancoo.ccas53.arrangecourse.entities.ClassHour;
import com.lancoo.ccas53.arrangecourse.entities.TimeslotRoom;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Description 排课冲突计算
 * @Author Fortysun
 * @Date 2023/4/24 15:53
 **/
@Slf4j
public class ClashesCompute extends ClashesRecordCompute {
    /**
     * 计算教室容量冲突
     * @param classHourA 课时对象
     * @param clashes 冲突数量
     * @return
     */
    public int computeClashes(CopyOnWriteArrayList<ClassHour> classHourList,
                              ClassHour classHourA,
                              int clashes) {
        //如果这个课时，已经设置过了教室冲突、教师冲突以及学生冲突，那么跳过这个课时的比较
        //减少计算量，提高效率
        if (classHourA.isRoomClash()
                && classHourA.isStudentClash()
                && classHourA.isTeacherClash()) {
            return clashes;
        }

        for (ClassHour classHourB : classHourList) {
            //如果教室课时分组对象为空，说明此授课类型教学班没有分配教室课时分组，
            //那么就不存在冲突检测的问题
            if (classHourB.getTimeslotRoom() == null) {
                //直接跳过本次循环，进入下一次循环
                continue;
            }

            //不同的授课类型教学班，存在周次交叉的情况
            if (!classHourA.getCourseUnit().getUnitId().equals(classHourB.getCourseUnit().getUnitId())) {
                //获取A课表记录的教室课时分组列表
                TimeslotRoom timeslotRoomA = classHourA.getTimeslotRoom();
                //获取A课表记录的教室课时分组列表
                TimeslotRoom timeslotRoomB  = classHourB.getTimeslotRoom();
                if (isWeekClash(timeslotRoomA.getWeeks(),
                        timeslotRoomB.getWeeks())) {
                    //当前classHourA的冲突类型计算，都已完成，所以break掉，去统计下一个的
                    if (isBreak(classHourA)) {
                        break;
                    }
                    else {
                        //统计教室冲突数
                        clashes = addRoomClashes(classHourA, classHourB, clashes);
                    }

                    //当前classHourA的冲突类型计算，都已完成，所以break掉，去统计下一个的
                    if (isBreak(classHourA)) {
                        break;
                    }
                    else {
                        //统计教师冲突数
                        clashes = addTeacherClashes(classHourA, classHourB, clashes);
                    }

                    //当教学班不是在线选课类型的时候，才需要记录学生安排冲突
                    if (classHourA.getCourseUnit().getTeachingClassType() != 1) {
                        //当前classHourA的冲突类型计算，都已完成，所以break掉，去统计下一个的
                        if (isBreak(classHourA)) {
                            break;
                        }
                        else {
                            //统计学生冲突数
                            clashes = addStudentClashes(classHourA, classHourB, clashes);
                        }
                    }
                }
            }
        }

        return clashes;
    }


    /**
     * 添加教室冲突
     * @param classHourA 排课单元
     * @param classHourB 排课单元
     * @param clashes  冲突数量
     * @return
     */
    private int addRoomClashes(ClassHour classHourA, ClassHour classHourB, int clashes) {

        //如果已标记，说明这种类型的冲突已经统计过，那么不再统计
        if (classHourA.isRoomClash()) {
            return clashes;
        }

        //获取A课表记录的教室课时分组列表
        TimeslotRoom timeslotRoomA = classHourA.getTimeslotRoom();
        //获取A课表记录的教室课时分组列表
        TimeslotRoom timeslotRoomB = classHourB.getTimeslotRoom();
        //不同的授课类型教学班，存在周次交叉的情况，并且对应的教室课时id相同，则教室、课时安排冲突
        if (timeslotRoomA.getTimeslotRoomId() == timeslotRoomB.getTimeslotRoomId()) {
            log.info("教室安排冲突 -- 教学班：" + classHourA.getCourseUnit().getTeachingClassName()
                    + ", 连上节次：" + classHourA.getCourseUnit().getConnectSection()
                    + ",教学班周次：" + classHourA.getCourseUnit().getClassWeeks()
                    + ",分配周次周次：" + timeslotRoomA.getWeeks()
                    + "， 和教学班：" +classHourB.getCourseUnit().getTeachingClassName()
                    + ",教学班周次：" + classHourB.getCourseUnit().getClassWeeks()
                    + ",分配周次周次：" + timeslotRoomB.getWeeks()
                    + "，在课时：" + timeslotRoomA.getTimeslotCode()
                    + "， 同时需要使用教室：" + timeslotRoomA.getRoomId());

//            log.info("教室安排冲突 -- 教学班：" + classHourA.getCourseUnit().getTeachingClassName()
//                    + "， 和教学班：" +classHourB.getCourseUnit().getTeachingClassName()
//                    + "，在课时：" + classHourA.getTimeslotRoom().getTimeslotCode()
//                    + "， 同时需要使用教室：" + classHourA.getTimeslotRoom().getRoomId());
            //将A的教室冲突标记设为已标记
            classHourA.setRoomClash(true);
            //针对A的冲突次数添加一次
            clashes++;
            //将B的教室冲突标记设置已标记
            classHourB.setRoomClash(true);
            //针对B的冲突次数添加一次,
            // 因为冲突是相互的，这样下次遍历到B的时候，就可以直接return掉了，不需要再进行判断操作
            clashes++;

            return clashes;
        }

        return clashes;
    }
    /**
     * 添加教室冲突
     * @param classHourA 排课单元
     * @param classHourB 排课单元
     * @param clashes  冲突数量
     * @return
     */
    private int addStudentClashes(ClassHour classHourA, ClassHour classHourB, int clashes) {
        //如果已标记，说明这种类型的冲突已经统计过，那么不再统计
        if (classHourA.isStudentClash()) {
            return clashes;
        }

        //计算冲突的学生的id
        String clashesStudentId = StrUtil.clashString(classHourA.getCourseUnit().getStudentIds(),
                classHourB.getCourseUnit().getStudentIds());
        //相同的课时，安排了相同的教师，那么教师冲突
        if (!StringUtils.isBlank(clashesStudentId)) {
            log.info("学生安排冲突 -- 教学班：" + classHourA.getCourseUnit().getTeachingClassName()
                    + "， 和教学班：" +classHourB.getCourseUnit().getTeachingClassName()
                    + "，在课时：" + classHourA.getTimeslotRoom().getTimeslotCode()
                    + "， 同时包含学生：" + clashesStudentId);
            //将A的学生冲突标记设为已标记
            classHourA.setStudentClash(true);
            //针对A的冲突次数添加一次
            clashes++;
            //将B的学生冲突标记设置已标记
            classHourB.setStudentClash(true);
            //针对B的冲突次数添加一次,
            // 因为冲突是相互的，这样下次遍历到B的时候，就可以直接return掉了，不需要再进行判断操作
            clashes++;
            return clashes;
        }

        return clashes;
    }
    /**
     * 添加教室冲突
     * @param classHourA 排课单元
     * @param classHourB 排课单元
     * @param clashes  冲突数量
     * @return
     */
    private int addTeacherClashes(ClassHour classHourA, ClassHour classHourB, int clashes) {
        //如果有一个教学班排课单元没有设置教师信息,不计算教师冲突
        if (StringUtils.isBlank(classHourA.getCourseUnit().getTeacherIds())
                || StringUtils.isBlank(classHourB.getCourseUnit().getTeacherIds())) {
            return clashes;
        }

        //如果已标记，说明这种类型的冲突已经统计过，那么不再统计
        if (classHourA.isTeacherClash()) {
            return clashes;
        }

        //计算冲突的教师的id
        String clashesTeacherId = StrUtil.clashString(classHourA.getCourseUnit().getTeacherIds(),
                classHourB.getCourseUnit().getTeacherIds());
        //相同的课时，安排了相同的教师，那么教师冲突
        if (!StringUtils.isBlank(clashesTeacherId)) {
            log.info("教师安排冲突 -- 教学班：" + classHourA.getCourseUnit().getTeachingClassName()
                    + "， 和教学班：" +classHourB.getCourseUnit().getTeachingClassName()
                    + "，在课时：" + classHourA.getTimeslotRoom().getTimeslotCode()
                    + "， 同时包含学生：" + clashesTeacherId);
            //将A的教师冲突标记设为已标记
            classHourA.setTeacherClash(true);
            //针对A的冲突次数添加一次
            clashes++;
            //将B的教师冲突标记设置已标记
            classHourB.setTeacherClash(true);
            //针对B的冲突次数添加一次,
            // 因为冲突是相互的，这样下次遍历到B的时候，就可以直接return掉了，不需要再进行判断操作
            clashes++;
            return clashes;
        }
        return clashes;
    }
}
